package me.luger.project.fof.controller.api;

import me.luger.core.commom.util.DateUtil;
import me.luger.core.commom.util.LogUtil;
import me.luger.core.mvc.controller.BaseController;
import me.luger.core.mvc.entity.Result;
import me.luger.project.fof.entity.*;
import me.luger.project.fof.entity.ext.ProfitAndRiskHistogram;
import me.luger.project.fof.service.*;
import org.apache.commons.collections.map.HashedMap;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
 * FOF结果展示相关指标 controller
 */
@Controller
@RequestMapping("/api/fof/fofResult")
public class FofResultApiController extends BaseController {


    @Autowired
    private FofResultService fofResultService;
    @Autowired
    private FofWeightDailyService fofWeightDailyService;
    @Autowired
    private FundNavService fundNavService;
    @Autowired
    private FofFundIndicatorService fofFundIndicatorService;
    @Autowired
    private FofInfoService fofInfoService;



    /**
     * 获取FOF对应基金每日权重
     * @param fofId
     * @return
     */
    @RequestMapping(value = "/getFofResult", name = "接口描述")
    @ResponseBody
    public Object getFofResult(Integer fofId, Integer backYearLength) {

        if(fofId == null) {
            return Result.error();
        }
        if(backYearLength == null) {
            backYearLength = 1;
        }

        Map<String, List<FofWeightDaily>> fwdMap = null;

        try {
            //计算规则为：FOF回测净值为最早一个FOF组合往前回测
            //结束时间为当前时间
            Date endDate = new Date();
            Date startDate = fofResultService.getFofResultFirstDayById(fofId);
            List<FofResult> firstFrList = fofResultService.getFofResultByIdAndDate(fofId, startDate);
            if(firstFrList == null || firstFrList.size() < 1) {
                return Result.error();
            }

            fwdMap = fofWeightDailyService.getFofWeightDaily(fofId, firstFrList, startDate);
        } catch (Exception e) {
            LogUtil.errorLog(e, "");
            return Result.error();
        }

        String fofName = null;
        FofInfo fofInfo = fofInfoService.getFofInfo(fofId);
        if(fofInfo != null) {
            fofName = fofInfo.getFullName();
        }

        Map<String, Object> result = new HashedMap();
        result.put("name", fofName);
        result.put("fundCombList", fwdMap);
        return Result.success(result);
    }

    /**
     * 获取FOF对应基金资产配置变化
     * @param fofId
     * @return
     */
    @RequestMapping(value = "/getFofAssetConf", name = "接口描述")
    @ResponseBody
    public Object getFofAssetConf(Integer fofId, Integer backYearLength) {

        if(fofId == null) {
            return Result.error();
        }
        if(backYearLength == null) {
            backYearLength = 1;
        }

        Map<String, List<FofWeightDaily>> fwdMap = null;

        try {
            //计算规则为：FOF回测净值为最早一个FOF组合往前回测
            //结束时间为当前时间
            Date endDate = new Date();
            Date startDate = fofResultService.getFofResultFirstDayById(fofId);
            List<FofResult> firstFrList = fofResultService.getFofResultByIdAndDate(fofId, startDate);
            if(firstFrList == null || firstFrList.size() < 1) {
                return Result.error();
            }

            fwdMap = fofWeightDailyService.getFofWeightDaily(fofId, firstFrList, startDate, 1, true);
        } catch (Exception e) {
            LogUtil.errorLog(e, "");
            return Result.error();
        }

        String fofName = null;
        FofInfo fofInfo = fofInfoService.getFofInfo(fofId);
        if(fofInfo != null) {
            fofName = fofInfo.getFullName();
        }

        Map<String, Object> result = new HashedMap();
        result.put("name", fofName);
        result.put("fundCombList", fwdMap);
        return Result.success(result);
    }

    /**
     * 获取FOF每日净值，可能为空
     * @param fofId
     * @return
     */
    @RequestMapping(value = "/getFofNav", name = "接口描述")
    @ResponseBody
    public Object getFofNav(Integer fofId, Integer backYearLength) {

        if(fofId == null) {
            return Result.error();
        }
        if(backYearLength == null) {
            backYearLength = 1;
        }

        //计算规则为：FOF回测净值为最早一个FOF组合往前回测
        //结束时间为当前时间
        Date endDate = new Date();
        Date startDate = fofResultService.getFofResultFirstDayById(fofId);
        Date fofStartDate = startDate;
        List<FofResult> firstFrList = fofResultService.getFofResultByIdAndDate(fofId, startDate);
        if(firstFrList == null || firstFrList.size() < 1) {
            return Result.error();
        }
        //调整回测时间
        Calendar c = Calendar.getInstance();
        c.setTime(startDate);
        c.add(Calendar.YEAR, -1 * backYearLength);
        startDate = c.getTime();
        if(endDate.compareTo(startDate) <= 0) {
            return Result.error();
        }

        String fofName = null;
        FofInfo fofInfo = fofInfoService.getFofInfo(fofId);
        if(fofInfo != null) {
            fofName = fofInfo.getFullName();
        }

        //FOF回测的起始日期，为子基金中净值起始点最晚的那天
        Date firstStartDay = fofWeightDailyService.calcFundStartDate(firstFrList, startDate, endDate);

        //回测净值列表，计算得到
        Map<String, Object> fnBackTestList = fofResultService.calcFofNavBackTest(fofId);

        //获取对应子基金及净值
        List<String> ecList = fofResultService.getFofFundExtCodeList(fofId);
        String[] extCodeArr = {};
        if(ecList != null && ecList.size() > 0) {
            extCodeArr = ecList.toArray(new String[ecList.size()]);
        }
        //获取子基金净值，从FOF创建的一年前开始到当天
        List fundsTrendList = fundNavService.getFundsTrendByDateRange(extCodeArr, firstStartDay, endDate);

        Map<String, Object> result = new HashedMap();
        result.put("name", fofName);
        result.put("startDate", DateUtil.format(fofStartDate, DateUtil.DATE_YYYY_MM_DD));
        if(fnBackTestList != null && fnBackTestList.size() > 0) {
            result.put("fofNavList", fnBackTestList.get("backTestPriceList"));
        } else {
            result.put("fofNavList", null);
        }
        result.put("fundList", fundsTrendList);
        return Result.success(result);
    }



    /**
     * 获取FOF每日净值，并保存到fund_nav中，以供yantao计算最大回撤
     * @param fofId
     * @return
     */
    @RequestMapping(value = "/getAndSaveFofNav", name = "接口描述")
    @ResponseBody
    public Object getAndSaveFofNav(Integer fofId, Integer backYearLength) {

        if(fofId == null) {
            return Result.error();
        }

        //计算规则为：FOF回测净值为最早一个FOF组合往前回测
        //结束时间为当前时间
        Date endDate = new Date();
        Date startDate = fofResultService.getFofResultFirstDayById(fofId);
        List<FofResult> firstFrList = fofResultService.getFofResultByIdAndDate(fofId, startDate);
        if(firstFrList == null || firstFrList.size() < 1) {
            return Result.error();
        }
        //调整回测时间
        Calendar c = Calendar.getInstance();
        c.setTime(startDate);
        c.add(Calendar.DATE, -1);
        startDate = c.getTime();
        if(endDate.compareTo(startDate) <= 0) {
            return Result.error();
        }

        String fofName = null;
        FofInfo fofInfo = fofInfoService.getFofInfo(fofId);
        if(fofInfo != null) {
            fofName = fofInfo.getFullName();
        }

        //回测净值列表，计算得到，不需要调整基金净值
        Map<String, Object> fnBackTestList = fofResultService.calcFofNavBackTest(fofId, 0);

        Map<String, Object> result = new HashedMap();
        if(fnBackTestList != null && fnBackTestList.size() > 0) {
            List<Map<String, Object>> backTestPriceList = (List<Map<String, Object>>)fnBackTestList.get("backTestPriceList");
            //检查库中是否有历史数据，更新或者插入
            String fofStr = "00000" + fofId.toString() + ".FOF";
            //FOF在fund_nav中以0000XX.FOF格式存储
            Integer fofStrLen = 10;
            if(fofStr.length() > fofStrLen) {
                fofStr = fofStr.substring(fofStr.length() - fofStrLen);
            }
            List<FundNav> fnList = fundNavService.getFundNavTrendByDateRange(fofStr, startDate, endDate);
            for(Map<String, Object> soMap : backTestPriceList) {
                String sday = (String)soMap.get("statisticDate");
                Double dnav = (Double)soMap.get("swanav");
                DecimalFormat df = new DecimalFormat("#.0000");
                df.format(dnav);
                Boolean found = false;
                if(fnList != null) {
                    for(FundNav fn : fnList) {
                        //找到，更新
                        String fnsday = DateUtil.format(fn.getStatisticDate(), DateUtil.DATE_YYYY_MM_DD);
                        if(fnsday.equals(sday)) {
                            Double sn = fn.getSwanav();
                            if(!df.format(sn).equals(df.format(dnav))) {
                                fn.setSwanav(dnav);
                                fn.setFundExtSource(3);
                                StringBuilder sqlBuilder = new StringBuilder("update fund_nav set swanav = @swanavValue where fund_ext_code = @fundExtCode and fund_ext_source = 3 and statistic_date = @statisticDate");
                                Sql sql = Sqls.create(sqlBuilder.toString());
                                sql.params().set("fundExtCode",fn.getFundExtCode());
                                sql.params().set("statisticDate",sday);
                                sql.params().set("swanavValue",dnav);
                                fundNavService.execute(sql);
                            }
                            found = true;
                        }
                    }
                }
                //没找到，插入
                if(!found) {
                    FundNav fn = new FundNav();
                    fn.setFundExtCode(fofStr);
                    fn.setFundExtSource(3);
                    fn.setStatisticDate(DateUtil.parseDate(sday, DateUtil.DATE_YYYY_MM_DD));
                    fn.setSwanav(dnav);
                    fundNavService.insert(fn);
                }
            }

            result.put("fofNavList", fnBackTestList.get("backTestPriceList"));
        } else {
            result.put("fofNavList", null);
        }
        return Result.success(result);
    }

    /**
     * 获取FOF最大回撤，可能为空
     * @param fofId
     * @return
     */
    @RequestMapping(value = "/getFofDrawDown", name = "接口描述")
    @ResponseBody
    public Object getFofDrawDown(Integer fofId) {

        List<FofFundIndicator> fddList = null;

        if(fofId == null) {
            return Result.error();
        }

        try {
            fddList = fofFundIndicatorService.getDrawDown(fofId, 3);
        } catch (Exception e) {
            LogUtil.errorLog(e, "");
            return Result.error();
        }

        String fofName = null;
        FofInfo fofInfo = fofInfoService.getFofInfo(fofId);
        if(fofInfo != null) {
            fofName = fofInfo.getFullName();
        }
        Map result = new HashedMap();
        result.put("name", fofName);
        result.put("drawDownList", fddList);

        return Result.success(result);
    }

    @RequestMapping(value = "/getProfitAndRisk",name = "接口描述")
    @ResponseBody
    public Object getProfitAndRisk(Integer fofId, Integer backYearLength){
        List<ProfitAndRiskHistogram> profitAndRiskHistogramList;
        try{
            profitAndRiskHistogramList = fofResultService.getProfitAndRisk(fofId,backYearLength);
        }catch (Exception e){
            return Result.error();
        }
        return Result.success().addDateItem("list",profitAndRiskHistogramList);
    }

    @RequestMapping(value = "",name = "接口描述")
    @ResponseBody
    public Object demo(){
        try{

        }catch (Exception e){
            return Result.error();
        }
        return Result.success();
    }
}
